package me.yuzho.study.concurrency;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

/** 
 * @author yzhou-citrix
 *
 */

class Count {
    private int count = 0;
    private Random rand = new Random(47);
    
    public synchronized int increment() { //去掉synchronized,程序会崩溃 
        int temp = count;
        if(rand.nextBoolean()) {
            Thread.yield();
        }
        return (count = ++temp);
    }
    
    public synchronized int value() { return count; }
}

class Entrance implements Runnable {
    private final int id;
    
    private static Count count = new Count(); //所有进出口共享一个记数器
    private static List<Entrance> entrances = new ArrayList<Entrance>(); //多个进出口
    
    private int number = 0;
    
    
    private static volatile boolean canceled = false;
    // Atomic operation on a volatile field
    public static void cancel() { canceled = true; }
    
    public Entrance(int id) {
        this.id = id;
        entrances.add(this); //将任务保存在一个列表中，并阻止僵死任务的垃圾回收
    }
    
    @Override
    public void run() {
        while(!canceled) {
            synchronized (this) {
                ++number;
            }
            
            System.out.println(this + " Total: " + count.increment());
            
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        System.out.println("Stopping " + this);
        
    }
    
    public synchronized int getValue() { return number; }

    @Override
    public String toString() {
        return String.format("Entrance %d: %d", id, getValue());
    }
    
    public static int getTotalCount() {
        return count.value();
    }
    
    public static int sumEntrances() {
        //return entrances.stream().map(e -> e.getValue()).reduce(Integer::sum).get();
        
        int sum =0;
        
        for(Entrance entrance : entrances) {
            sum += entrance.getValue();
            
        }
        
        return sum;
    }
    
}

public class OrnamentalGarden {

    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newCachedThreadPool();
        /* 使用下面的方式去创建Entrance,Entrance列表中有可能是null,估计是parallel的问题
        IntStream.range(0, 5).parallel().forEach(id -> {
            executor.execute(new Entrance(id));
        });*/
        
        IntStream.range(0, 5).forEach(id -> {
            executor.execute(new Entrance(id));
        });
        
        /*
        for(int i=0; i<5; i++){
            executor.execute(new Entrance(i));
        }*/
        
        TimeUnit.SECONDS.sleep(3);
        //System.out.println("Sum of Entrances: " + Entrance.sumEntrances());
        Entrance.cancel();
        executor.shutdown();
        
        //等待250ms,让所有线程都执行结束
        if(!executor.awaitTermination(250, TimeUnit.MILLISECONDS)) {
            System.out.println("Some tasks were not terminated");
        }
        
        System.out.println("Total: " + Entrance.getTotalCount());
        System.out.println("Sum of Entrances: " + Entrance.sumEntrances());
    }
}
